package imai78gae.heya.util;

import imai78gae.heya.exception.ParameterInvalidException;
import imai78gae.heya.model.Group;
import imai78gae.heya.model.Message;
import imai78gae.heya.model.UserInfo;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.Key;

/**
 * エンティティやモデルをディープコピーする為のユーティリティです。
 * 
 * @author imai78
 *
 */
public class ModelCopyUtil {

	/**
	 * {@link UserInfo}をコピーして複製を返します。
	 * <p>
	 * {@code user}に{@code null}を渡された場合、{@link ParameterInvalidException}の例外が返されます。
	 * </p>
	 * 
	 * @param user コピーしたい{@link UserInfo}
	 * @return 複製の{@link UserInfo}
	 */
	public static UserInfo copyUserInfo(UserInfo user) {
		if (user == null) {
			throw new ParameterInvalidException("user is null.");
		}
		UserInfo result = new UserInfo();
		result.setLoginId(user.getLoginId());
		result.setLoginPw(user.getLoginPw());
		result.setAccountName(user.getAccountName());
		result.setRegistered(user.getRegistered());
		return result;
	}

	/**
	 * {@link Message}をコピーして複製を返します。
	 * <p>
	 * {@code message}に{@code null}を渡された場合、{@link ParameterInvalidException}の例外が返されます。
	 * </p>
	 * 
	 * @param message コピーしたい{@link Message}
	 * @return 複製の{@link Message}
	 */
	public static Message copyMessage(Message message) {
		if (message == null) {
			throw new ParameterInvalidException("message is null.");
		}
		Message result = new Message();
		result.setAuthor(message.getAuthor());
		result.setContent(message.getContent());
		result.setRegistered(message.getRegistered());
		return result;
	}

	/**
	 * {@link Group}をコピーして複製を返します。
	 * <p>
	 * {@link Group}に従属する{@link Message}が存在した場合、それらも全てコピーされます。
	 * <br />
	 * それ以外の{@link Key}以外の情報は全てコピーされます。
	 * </p>
	 * 
	 * @param group コピーしたい{@link Group}
	 * @return 複製の{@link Group}
	 */
	public static Group copyGroup(Group group) {
		return copyGroup(group, true);
	}

	/**
	 * {@link Group}をコピーして複製を返します。
	 * <p>
	 * 引数{@code isMsgCopy}が{@code true}の場合は従属する{@link Message}を全てコピーしようとします。
	 * <br />
	 * 逆に引数{@code isMsgCopy}が{@code false}の場合、従属する{@link Message}のコピーを行いません。
	 * <br />
	 * それ以外の{@link Key}以外の情報は全てコピーされます。
	 * </p>
	 * <p>
	 * {@code group}に{@code null}を渡された場合、{@link ParameterInvalidException}の例外が返されます。
	 * </p>
	 * 
	 * @param group コピーしたい{@link Group}
	 * @param isMsgCopy {@link Group}に従属する{@link Message}をコピーするかどうかを指定します。
	 * @return 複製の{@link Group}
	 */
	public static Group copyGroup(Group group, boolean isMsgCopy) {
		if (group == null) {
			throw new ParameterInvalidException("group is null.");
		}
		// Groupのコピー
		Group result = new Group();
		result.setGroupId(group.getGroupId());
		result.setGroupName(group.getGroupName());
		result.setGroupDescription(group.getGroupDescription());
		result.setInviteKey(group.getInviteKey());
		result.setGroupOwnerId(group.getGroupOwnerId());
		result.setGroupOwnerName(group.getGroupOwnerName());
		result.setRegistered(group.getRegistered());
		// Messageのコピー
		if (isMsgCopy) {
			List<Message> newMsgList = new ArrayList<Message>();
			List<Message> msgList = group.getMessages();
			for (Message msg : msgList) {
				newMsgList.add(copyMessage(msg));
			}
			result.setMessages(newMsgList);
		}
		// メンバーのコピー
		List<String> newMembers = new ArrayList<String>();
		List<String> members = group.getMemberLoginIdList();
		for (String member : members) {
			newMembers.add(member);
		}
		result.setMemberLoginIdList(newMembers);
		return result;
	}

}
